home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / glibc-1.09 / glibc-1 / glibc-1.09.1 / hurd / hurdlookup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-12  |  9.2 KB  |  374 lines

  1. /* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <hurd.h>
  20. #include <string.h>
  21. #include <limits.h>
  22. #include <fcntl.h>
  23. #include "stdio/_itoa.h"
  24. #include <hurd/term.h>
  25.  
  26.  
  27. /* Translate the error from dir_lookup into the error the user sees.  */
  28. static inline error_t
  29. lookup_error (error_t error)
  30. {
  31.   switch (error)
  32.     {
  33.     case EOPNOTSUPP:
  34.     case MIG_BAD_ID:
  35.       /* These indicate that the server does not understand dir_lookup
  36.      at all.  If it were a directory, it would, by definition.  */
  37.       return ENOTDIR;
  38.     default:
  39.       return error;
  40.     }
  41. }
  42.  
  43. error_t
  44. __hurd_file_name_lookup (file_t crdir, file_t cwdir,
  45.              const char *file_name, int flags, mode_t mode,
  46.              file_t *result)
  47. {
  48.   error_t err;
  49.   enum retry_type doretry;
  50.   char retryname[1024];        /* XXX string_t LOSES! */
  51.   file_t startdir;
  52.  
  53.   startdir = file_name[0] == '/' ? crdir : cwdir;
  54.  
  55.   while (file_name[0] == '/')
  56.     file_name++;
  57.  
  58.   if (err = __dir_lookup (startdir, file_name, flags, mode,
  59.               &doretry, retryname, result))
  60.     return lookup_error (err);
  61.  
  62.   return __hurd_file_name_lookup_retry (crdir, doretry, retryname, flags, mode,
  63.                     result);
  64. }
  65.  
  66. error_t
  67. __hurd_file_name_lookup_retry (file_t crdir,
  68.                    enum retry_type doretry,
  69.                    char retryname[1024],
  70.                    int flags, mode_t mode,
  71.                    file_t *result)
  72. {
  73.   error_t err;
  74.   file_t startdir;
  75.   file_t newpt;
  76.   char *file_name;
  77.   int dealloc_dir;
  78.   int nloops;
  79.  
  80.   dealloc_dir = 0;
  81.   nloops = 0;
  82.   err = 0;
  83.   
  84.   while (1)
  85.     {
  86.       if (dealloc_dir)
  87.     __mach_port_deallocate (__mach_task_self (), startdir);
  88.       if (err)
  89.     return lookup_error (err);
  90.  
  91.       switch (doretry)
  92.     {
  93.     case FS_RETRY_REAUTH:
  94.       {
  95.         mach_port_t ref = __mach_reply_port ();
  96.         err = __io_reauthenticate (*result,
  97.                        ref, MACH_MSG_TYPE_MAKE_SEND);
  98.         if (! err)
  99.           err = __USEPORT
  100.         (AUTH, __auth_user_authenticate (port, *result,
  101.                          ref,
  102.                          MACH_MSG_TYPE_MAKE_SEND,
  103.                          &newpt));
  104.         __mach_port_destroy (__mach_task_self (), ref);
  105.       }
  106.       __mach_port_deallocate (__mach_task_self (), *result);
  107.       if (err)
  108.         return err;
  109.       *result = newpt;
  110.       /* Fall through.  */
  111.  
  112.     case FS_RETRY_NORMAL:
  113. #ifdef SYMLOOP_MAX
  114.       if (nloops++ >= SYMLOOP_MAX)
  115.         return ELOOP;
  116. #endif
  117.  
  118.       /* An empty RETRYNAME indicates we have the final port.  */
  119.       if (retryname[0] == '\0')
  120.         {
  121.           /* We got a successful translation.  Now apply any open-time
  122.          action flags we were passed.  */
  123.           if (flags & O_EXLOCK)
  124.         ;        /* XXX */
  125.           if (!err && (flags & O_SHLOCK))
  126.         ;        /* XXX */
  127.           if (!err && (flags & O_TRUNC))
  128.         err = __file_truncate (*result, 0);
  129.  
  130.           if (err)
  131.         __mach_port_deallocate (__mach_task_self (), *result);
  132.           return err;
  133.         }
  134.  
  135.       startdir = *result;
  136.       dealloc_dir = 1;
  137.       file_name = retryname;
  138.       break;
  139.  
  140.     case FS_RETRY_MAGICAL:
  141.       switch (retryname[0])
  142.         {
  143.         case '/':
  144.           startdir = crdir;
  145.           dealloc_dir = 0;
  146.           if (*result != MACH_PORT_NULL)
  147.         __mach_port_deallocate (__mach_task_self (), *result);
  148.           file_name = &retryname[1];
  149.           break;
  150.  
  151.         case 'f':
  152.           if (retryname[1] == 'd' && retryname[2] == '/')
  153.         {
  154.           int fd;
  155.           char *end;
  156.           int save = errno;
  157.           errno = 0;
  158.           fd = (int) strtol (retryname, &end, 10);
  159.           if (end == NULL || errno || /* Malformed number.  */
  160.               /* Check for excess text after the number.  A slash
  161.              is valid; it ends the component.  Anything else
  162.              does not name a numeric file descriptor.  */
  163.               (*end != '/' && *end != '\0'))
  164.             {
  165.               errno = save;
  166.               return ENOENT;
  167.             }
  168.           *result = __getdport (fd);
  169.           if (*result == MACH_PORT_NULL)
  170.             {
  171.               /* If the name was a proper number, but the file
  172.              descriptor does not exist, we return EBADF instead
  173.              of ENOENT.  */
  174.               error_t err = errno;
  175.               errno = save;
  176.               return err;
  177.             }
  178.           errno = save;
  179.           if (*end == '\0')
  180.             return 0;
  181.           else
  182.             {
  183.               /* Do a normal retry on the remaining components.  */
  184.               startdir = *result;
  185.               dealloc_dir = 1;
  186.               file_name = end + 1; /* Skip the slash.  */
  187.               break;
  188.             }
  189.         }
  190.           else
  191.         goto bad_magic;
  192.           break;
  193.  
  194.         case 'm':
  195.           if (retryname[1] == 'a' && retryname[2] == 'c' &&
  196.           retryname[3] == 'h' && retryname[4] == 't' &&
  197.           retryname[5] == 'y' && retryname[6] == 'p' &&
  198.           retryname[7] == 'e')
  199.         {
  200.           error_t err;
  201.           struct host_basic_info hostinfo;
  202.           unsigned int hostinfocnt = HOST_BASIC_INFO_COUNT;
  203.           char *p;
  204.           if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO,
  205.                      (int *) &hostinfo, &hostinfocnt))
  206.             return err;
  207.           if (hostinfocnt != HOST_BASIC_INFO_COUNT)
  208.             return EGRATUITOUS;
  209.           p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0);
  210.           *--p = '/';
  211.           p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0);
  212.           if (p < retryname)
  213.             abort ();    /* XXX write this right if this ever happens */
  214.           if (p > retryname)
  215.             strcpy (retryname, p);
  216.           startdir = *result;
  217.           dealloc_dir = 1;
  218.         }
  219.           else
  220.         goto bad_magic;
  221.           break;
  222.  
  223.         case 't':
  224.           if (retryname[1] == 't' && retryname[2] == 'y')
  225.         switch (retryname[3])
  226.           {
  227.             error_t opentty (file_t *result)
  228.               {
  229.             error_t err;
  230.             file_t unauth;
  231.             err = __USEPORT (CTTYID,
  232.                      __termctty_open_terminal (port,
  233.                                    flags,
  234.                                    &unauth));
  235.             if (! err)
  236.               {
  237.                 mach_port_t ref = __mach_reply_port ();
  238.                 err = __io_reauthenticate
  239.                   (unauth,
  240.                    ref,
  241.                    MACH_MSG_TYPE_MAKE_SEND);
  242.                 if (! err)
  243.                   err = __USEPORT
  244.                 (AUTH, __auth_user_authenticate
  245.                  (port,
  246.                   unauth,
  247.                   ref, MACH_MSG_TYPE_MAKE_SEND,
  248.                   result));
  249.                 __mach_port_deallocate (__mach_task_self (),
  250.                             unauth);
  251.                 __mach_port_destroy (__mach_task_self (), ref);
  252.               }
  253.             return err;
  254.               }
  255.  
  256.           case '\0':
  257.             return opentty (result);
  258.           case '/':
  259.             if (err = opentty (&startdir))
  260.               return err;
  261.             dealloc_dir = 1;
  262.             strcpy (retryname, &retryname[4]);
  263.             break;
  264.           default:
  265.             goto bad_magic;
  266.           }
  267.           else
  268.         goto bad_magic;
  269.           break;
  270.  
  271.         default:
  272.         bad_magic:
  273.           return EGRATUITOUS;
  274.         }
  275.       break;        
  276.  
  277.     default:
  278.       return EGRATUITOUS;
  279.     }
  280.  
  281.       err = __dir_lookup (startdir, file_name, flags, mode,
  282.               &doretry, retryname, result);
  283.     }
  284. }
  285.  
  286. error_t
  287. __hurd_file_name_split (file_t crdir, file_t cwdir,
  288.             const char *file_name,
  289.             file_t *dir, char **name)
  290. {
  291.   const char *lastslash;
  292.   error_t err;
  293.  
  294.   lastslash = strrchr (file_name, '/');
  295.   if (lastslash != NULL)
  296.     {
  297.       if (lastslash == file_name)
  298.     {
  299.       /* "/foobar" => crdir + "foobar".  */
  300.       *name = (char *) file_name + 1;
  301.       if (err = __mach_port_mod_refs (__mach_task_self (), 
  302.                       crdir, MACH_PORT_RIGHT_SEND, +1))
  303.         return err;
  304.       *dir = crdir;
  305.       return 0;
  306.     }
  307.       else
  308.     {
  309.       /* "/dir1/dir2/.../file".  */
  310.       char dirname[lastslash - file_name + 1];
  311.       memcpy (dirname, file_name, lastslash - file_name);
  312.       dirname[lastslash - file_name] = '\0';
  313.       *name = (char *) lastslash + 1;
  314.       return __hurd_file_name_lookup (crdir, cwdir, dirname, 0, 0, dir);
  315.     }
  316.     }
  317.   else
  318.     {
  319.       /* "foobar" => cwdir + "foobar".  */
  320.       *name = (char *) file_name;
  321.       if (err = __mach_port_mod_refs (__mach_task_self (),
  322.                       cwdir, MACH_PORT_RIGHT_SEND, +1))
  323.     return err;
  324.       *dir = cwdir;
  325.       return 0;
  326.     }
  327. }
  328.  
  329. file_t
  330. __file_name_lookup (const char *file_name, int flags, mode_t mode)
  331. {
  332.   error_t err;
  333.   file_t result, crdir, cwdir;
  334.   struct hurd_userlink crdir_ulink, cwdir_ulink;
  335.  
  336.   crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink);
  337.   cwdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink);
  338.  
  339.   err = __hurd_file_name_lookup (crdir, cwdir, file_name, flags, mode,
  340.                  &result);
  341.  
  342.   _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink, crdir);
  343.   _hurd_port_free (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink, cwdir);
  344.  
  345.   if (err)
  346.     return __hurd_fail (err), MACH_PORT_NULL;
  347.   else
  348.     return result;
  349. }
  350.  
  351. file_t
  352. __file_name_split (const char *file_name, char **name)
  353. {
  354.   error_t err;
  355.   file_t dir, crdir, cwdir;
  356.   struct hurd_userlink crdir_ulink, cwdir_ulink;
  357.  
  358.   crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink);
  359.   cwdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink);
  360.  
  361.   err = __hurd_file_name_split (crdir, cwdir, file_name, &dir, name);
  362.  
  363.   _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink, crdir);
  364.   _hurd_port_free (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink, cwdir);
  365.  
  366.   if (err)
  367.     {
  368.       errno = err;
  369.       return MACH_PORT_NULL;
  370.     }
  371.   else
  372.     return dir;
  373. }
  374.